package com.huike.report.service.impl;

import com.huike.business.mapper.TbBusinessMapper;
import com.huike.clues.domain.SubjectStatic;
import com.huike.clues.domain.TbActivity;
import com.huike.clues.domain.TbAssignRecord;
import com.huike.clues.domain.TbClue;
import com.huike.clues.domain.vo.IndexStatisticsVo;
import com.huike.clues.mapper.*;
import com.huike.common.core.domain.entity.SysDept;
import com.huike.common.core.domain.entity.SysRole;
import com.huike.common.core.domain.entity.SysUser;
import com.huike.common.utils.DateUtils;
import com.huike.common.utils.SecurityUtils;
import com.huike.contract.domain.TbContract;
import com.huike.contract.mapper.TbContractMapper;
import com.huike.report.domain.vo.*;
import com.huike.report.mapper.ReportMapper;
import com.huike.report.service.IReportService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;

@Service
public class ReportServiceImpl implements IReportService {

    @Autowired
    private TbContractMapper contractMapper;


    @Autowired
    private SysDictDataMapper sysDictDataMapper;


    @Autowired
    private TbClueMapper clueMapper;

    @Autowired
    private TbActivityMapper activityMapper;

    @Autowired
    private TbBusinessMapper businessMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private TbAssignRecordMapper assignRecordMapper;

    @Autowired
    private ReportMapper reportMpper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Override
    public LineChartVO contractStatistics(String beginCreateTime, String endCreateTime) {
        LineChartVO lineChartVo =new LineChartVO();
        try {
            List<String> timeList= findDates(beginCreateTime,endCreateTime);
            lineChartVo.setxAxis(timeList);
            List<LineSeriesVO> series = new ArrayList<>();
            List<Map<String,Object>>  statistics = contractMapper.contractStatistics(beginCreateTime,endCreateTime);
            LineSeriesVO lineSeriesDTO1=new LineSeriesVO();
            lineSeriesDTO1.setName("新增客户数");
            LineSeriesVO lineSeriesDTO2=new LineSeriesVO();
            lineSeriesDTO2.setName("客户总数");
            int sum = 0;
            for (String s : timeList) {
                Optional optional=  statistics.stream().filter(d->d.get("dd").equals(s)).findFirst();
                if(optional.isPresent()){
                    Map<String,Object> cuurentData=  (Map<String,Object>)optional.get();
                    lineSeriesDTO1.getData().add(cuurentData.get("num"));
                    sum += Integer.parseInt(cuurentData.get("num").toString());
                }else{
                    lineSeriesDTO1.getData().add(0);
                }
                lineSeriesDTO2.getData().add(sum);
            }
            series.add(lineSeriesDTO1);
            series.add(lineSeriesDTO2);
            lineChartVo.setSeries(series);
        } catch (ParseException e) {
            // e.printStackTrace();
        }
        return  lineChartVo;
    }

    @Override
    public LineChartVO salesStatistics(String beginCreateTime, String endCreateTime) {
        LineChartVO lineChartVo =new LineChartVO();
        try {
            List<String> timeList= findDates(beginCreateTime,endCreateTime);
            lineChartVo.setxAxis(timeList);
            List<LineSeriesVO> series = new ArrayList<>();
            List<Map<String,Object>>  statistics = contractMapper.salesStatistics(beginCreateTime,endCreateTime);
            LineSeriesVO lineSeriesVo=new LineSeriesVO();
            lineSeriesVo.setName("销售统计");
            int sum=0;
            for (String s : timeList) {
                Optional optional=  statistics.stream().filter(d->d.get("dd").equals(s)).findFirst();
                if(optional.isPresent()){
                    Map<String,Object> cuurentData=  (Map<String,Object>)optional.get();
                    lineSeriesVo.getData().add(cuurentData.get("sales"));
                }else{
                    lineSeriesVo.getData().add(0);
                }
            }
            series.add(lineSeriesVo);
            lineChartVo.setSeries(series);
        } catch (ParseException e) {
            // e.printStackTrace();
        }
        return  lineChartVo;
    }




    /**
     * 渠道统计
     */
    @Override
    public List<Map<String, Object>> chanelStatistics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.chanelStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            String subjectValue= (String) datum.get("channel");
            String lable=  sysDictDataMapper.selectDictLabel("clues_item",subjectValue);
            datum.put("channel",lable);
        }
        return data;
    }

    @Override
    public List<TbContract> contractReportList(TbContract tbContract) {
        return contractMapper.selectTbContractList(tbContract);
    }


    @Override
    public List<Map<String, Object>> activityStatistics(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.activityStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            Long activityId= (Long) datum.get("activity_id");
            TbActivity tbActivity = activityMapper.selectTbActivityById(activityId);
            if(tbActivity==null){
                datum.put("activity", "其他");
            }else{
                datum.put("activity", tbActivity.getName());
            }
        }
        return data;
    }

    /**
     * 按照部门统计销售
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> deptStatisticsList(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.deptStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            Long deptId= (Long) datum.get("dept_id");
            if(deptId!=null){
                SysDept dept= deptMapper.selectDeptById(deptId);
                datum.put("deptName", dept.getDeptName());
            }
        }
        return data;
    }


    /**
     * 按照渠道统计销售
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> channelStatisticsList(String beginCreateTime, String endCreateTime) {
        List<Map<String, Object>> data= contractMapper.channelStatistics(beginCreateTime,endCreateTime);
        for (Map<String, Object> datum : data) {
            String subjectValue= (String) datum.get("channel");
            if(subjectValue!=null){
                String lable=  sysDictDataMapper.selectDictLabel("clues_item",subjectValue);
                datum.put("channel",lable);
            }
        }
        return data;
    }


    /**
     * 按照归属人统计销售
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> ownerShipStatisticsList(String beginCreateTime, String endCreateTime) {
        return  contractMapper.ownerShipStatistics(beginCreateTime,endCreateTime);
    }


    @Override
    public List<TbClue> cluesStatisticsList(TbClue clue) {
        return clueMapper.selectTbClueForReport(clue);
    }

    @Override
    public List<ActivityStatisticsVo> activityStatisticsList(TbActivity query) {
        query.setStatus("2");
        List<TbActivity> activities= activityMapper.selectTbActivityList(query);
        Map<String, Object> timeMap = query.getParams();
        List<ActivityStatisticsVo> list=new ArrayList<>();
        for (TbActivity activity : activities) {
            ActivityStatisticsVo dto = new ActivityStatisticsVo();
            BeanUtils.copyProperties(activity, dto);
            TbClue tbClue = new TbClue();
            tbClue.setActivityId(activity.getId());
            tbClue.setChannel(activity.getChannel());
            tbClue.setParams(timeMap);
            Map<String, Object> clueCount = clueMapper.countByActivity(tbClue);
            if (clueCount != null) {
                dto.setCluesNum(Integer.parseInt(clueCount.get("total").toString()));
                if(clueCount.get("falseClues")!=null){
                    dto.setFalseCluesNum(Integer.parseInt(clueCount.get("falseClues").toString()));
                }
                if (clueCount.get("toBusiness") != null) {
                    dto.setBusinessNum(Integer.parseInt(clueCount.get("toBusiness").toString()));
                }
            }
            TbContract tbContract = new TbContract();
            tbContract.setChannel(activity.getChannel());
            tbContract.setActivityId(activity.getId());
            tbContract.setParams(timeMap);
            Map<String, Object> contractCount = contractMapper.countByActivity(tbContract);
            if (contractCount != null) {
                dto.setCustomersNum(Integer.parseInt(contractCount.get("customersNum").toString()));
                if(contractCount.get("amount")==null) {
                    dto.setAmount(0d);
                }else {
                    dto.setAmount((Double) contractCount.get("amount"));
                }
                if(contractCount.get("cost")==null) {
                    dto.setCost(0d);
                }else {
                    dto.setCost((Double) contractCount.get("cost"));
                }

            }
            list.add(dto);
        }
        return list;
    }

    /**
     * *************看我看我**************
     * 传入两个时间范围，返回这两个时间范围内的所有时间，并保存在一个集合中
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<String> findDates(String beginTime, String endTime)
            throws ParseException {
        List<String> allDate = new ArrayList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Date dBegin = sdf.parse(beginTime);
        Date dEnd = sdf.parse(endTime);
        allDate.add(sdf.format(dBegin));
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            allDate.add(sdf.format(calBegin.getTime()));
        }
        System.out.println("时间==" + allDate);
        return allDate;
    }


    @Override
    public IndexVo getIndex(IndexStatisticsVo request) {
        Long deptId= request.getDeptId();
        TbAssignRecord tbAssignRecord=new TbAssignRecord();
        tbAssignRecord.setLatest("1");
        assignRecordMapper.selectAssignRecordList(tbAssignRecord);
        return null;
    }

    @Override
    public List<Map<String, Object>> salesStatisticsForIndex(IndexStatisticsVo request) {
        List<Map<String, Object>> list= contractMapper.contractStatisticsByUser(request);
        for (Map<String, Object> datum : list) {
            Long deptId= (Long) datum.get("dept_id");
            if(deptId!=null){
                SysDept dept= deptMapper.selectDeptById(deptId);
                datum.put("deptName", dept.getDeptName());
            }
        }
        return list;
    }


    /**
     * ************看我看我***********
     * 用我能少走很多路
     * 我是用来机选百分比的方法
      * @param all
     * @param num
     * @return
     */
    private BigDecimal getRadio(Integer all,Long num) {
        if(all.intValue()==0){
            return new BigDecimal(0);
        }
        BigDecimal numBigDecimal = new BigDecimal(num);
        BigDecimal allBigDecimal = new BigDecimal(all);
        BigDecimal divide = numBigDecimal.divide(allBigDecimal,4,BigDecimal.ROUND_HALF_UP);
        return divide.multiply(new BigDecimal(100));
    }


    /**
     * 获取首页基本数据
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public IndexBaseInfoVO getBaseInfo(String beginCreateTime, String endCreateTime) {
        //1）构建一个空的结果集对象
        IndexBaseInfoVO result = new IndexBaseInfoVO();
        //2 封装结果集属性
        // 2.1 由于查询需要用到用户名 调用工具类获取用户名
        String username = SecurityUtils.getUsername();
        try {
            //3 封装结果集对象
/*            CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
                @Override
                public Integer get() {
                    return reportMpper.getCluesNum(beginCreateTime, endCreateTime, username);
                }
            });*/
            CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> reportMpper.getCluesNum(beginCreateTime, endCreateTime, username));
            CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> reportMpper.getBusinessNum(beginCreateTime, endCreateTime, username));
            CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> reportMpper.getContractNum(beginCreateTime, endCreateTime, username));
            CompletableFuture<Double> task4 = CompletableFuture.supplyAsync(() -> reportMpper.getSalesAmount(beginCreateTime, endCreateTime, username));

            CompletableFuture.allOf(task1,task2,task3,task4).join();

            result.setCluesNum(task1.get());
            result.setBusinessNum(task2.get());
            result.setContractNum(task3.get());
            result.setSalesAmount(task4.get());
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        //4 返回结果集对象
        return result;
    }
    /**
     * @description: 获取今日数据统计
     * @return: com.huike.report.domain.vo.IndexBaseInfoVO
     * @author: ShaJianBao
     * @date: 2022/9/5 15:07
     */
    @Override
    public IndexTodayInfo getTodayInfo() {
        //1）构建一个空的结果集对象
        IndexTodayInfo result = new IndexTodayInfo();
        //2 封装结果集属性
        // 2.1 由于查询需要用到用户名 调用工具类获取用户名
        String username = SecurityUtils.getUsername();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String date = simpleDateFormat.format(new Date());
        try {
            //3 封装结果集对象
            CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> reportMpper.getCluesNumByDate(date, username));
            CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> reportMpper.getBusinessNumByDate(date, username));
            CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> reportMpper.getContractNumByDate(date, username));
            CompletableFuture<Double> task4 = CompletableFuture.supplyAsync(() -> reportMpper.getSalesAmountByDate(date, username));

            CompletableFuture.allOf(task1,task2,task3,task4).join();

            result.setTodayCluesNum(task1.get());
            result.setTodayBusinessNum(task2.get());
            result.setTodayContractNum(task3.get());
            result.setTodaySalesAmount(task4.get());
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        //4 返回结果集对象
        return result;
    }
    /**
     * @description: 首页--待办数据统计接口
     * @param: beginCreateTime :开始日期
     * @param: endCreateTime : 结束日期
     * @return: com.huike.report.domain.vo.IndexTodayInfoVO
     * @author: ShaJianBao
     * @date: 2022/9/5 17:24
     */
    @Override
    public IndexTodoInfo getTodoInfo(String beginCreateTime, String endCreateTime) {
        IndexTodoInfo result = new IndexTodoInfo();
        String username = SecurityUtils.getUsername();
        //获取用户的角色,如果是管理员或者主管则显示待分配线索 和商机
        SysUser sysUser = sysUserMapper.selectUserByUserName(username);
        //获取用户权限
        List<SysRole> roles = sysUser.getRoles();
        try {
            //循环判断不同角色对应的权限
            CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> reportMpper.getTofollowedCluesNum(beginCreateTime,endCreateTime, username));
            CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> reportMpper.getTofollowedBusinessNum(beginCreateTime,endCreateTime, username));
            CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> reportMpper.getToallocatedCluesNum(beginCreateTime,endCreateTime, username));
            CompletableFuture<Integer> task4 = CompletableFuture.supplyAsync(() -> reportMpper.getToallocatedBusinessNum(beginCreateTime,endCreateTime, username));

            CompletableFuture.allOf(task1,task2,task3,task4).join();

            for (SysRole role : roles) {
                if("2".equals(role.getRoleSort())){
                    result.setTofollowedCluesNum(task1.get());
                }else if("3".equals(role.getRoleSort())){
                    result.setTofollowedBusinessNum(task2.get());
                } else {
                    result.setToallocatedCluesNum(task3.get());
                    result.setToallocatedBusinessNum(task4.get());
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return result;
    }
    /**
     * @description: 学科客户分布统计
     * @param: beginCreateTime
     * @param: endCreateTime
     * @return: java.util.List<com.huike.clues.domain.SubjectStatic>
     * @author: ShaJianBao
     * @date: 2022/9/5 21:51
     */
    @Override
    public List<SubjectStatic> subjectStatistics(String beginCreateTime, String endCreateTime) {
        List<SubjectStatic> list=reportMpper.getSubjectStatistics(beginCreateTime,endCreateTime);
        return list;
    }
    /**
     * @description: 新增线索数量折线图
     * @param: beginCreateTime
     * @param: endCreateTime
     * @return: com.huike.clues.domain.CluesStatic
     * @author: ShaJianBao
     * @date: 2022/9/6 8:48
     */
    @Override
    public LineChart cluesStatistics(String beginCreateTime, String endCreateTime) {
        //将传入的日期字符转换为日期
        Date beginDate = DateUtils.dateTime(DateUtils.YYYY_MM_DD, beginCreateTime);
        Date endDate = DateUtils.dateTime(DateUtils.YYYY_MM_DD, endCreateTime);
        //计算两个日志之间的天数查
        int num = (int)((endDate.getTime() - beginDate.getTime()) / (1000 * 60 * 60 * 24L));
        //新建数组,长度为 num +1
        //记录天数字符串
        List<String> dateList = new ArrayList<>();
        //记录每日新增数量
        List<Object> dayClue = new ArrayList<>();
        //记录每日线索总数量
        List<Object> totalClue = new ArrayList<>();
        Date tmeDate = new Date();
        //记录线索总数
        Integer count=new Integer(0);
        tmeDate=beginDate;

        //循环处理每一天数据
        for (int i = 0; i < num+1; i++) {
            String tempStringDate = DateUtils.dateTime(tmeDate);
            //记录日期
            dateList.add(tempStringDate) ;
            //记录当日新增线索
            Integer dayNum = reportMpper.getNewIncreamentClueByDate(tempStringDate);
            dayClue.add(dayNum);
            //累加线索总数量
            count=count+dayNum;
            totalClue.add(count);

            //临时日期增加1天
            tmeDate=new Date(tmeDate.getTime()+1000*60*60*24L);
        }
        //返回题组装
        LineChart lineChartVO = new LineChart();
        lineChartVO.setxAxis(dateList);
        //组装 新增线索
        LineSeriesVO lineSeriesVO1 = new LineSeriesVO();
        lineSeriesVO1.setName("新增线索数量");
        lineSeriesVO1.setData(dayClue);
        //组装 线索总数
        LineSeriesVO lineSeriesVO2 = new LineSeriesVO();
        lineSeriesVO2.setName("线索总数量");
        lineSeriesVO2.setData(totalClue);
        //组装 List
        List<LineSeriesVO> list = new ArrayList<>();
        list.add(lineSeriesVO1);
        list.add(lineSeriesVO2);

        lineChartVO.setSeries(list);

        return lineChartVO;
    }
    /**
     * @description: 线索转化率漏斗图
     * @param: beginCreateTime
     * @param: endCreateTime
     * @return: com.huike.report.domain.vo.VulnerabilityMapVo
     * @author: ShaJianBao
     * @date: 2022/9/6 14:29
     */
    @Override
    public VulnerabilityMap getVulnerabilityMap(String beginCreateTime, String endCreateTime) {
        VulnerabilityMap vulnerabilityMap = new VulnerabilityMap();
        //线索数量   线索不用考虑状态有多少线索全部统计
        //有效线索数 待跟进，跟进中，转换成商机，转换成客户
        //商机数量   待跟进， 根进中,  转换成客户
        //合同数量   转换成合同的不用考虑状态，只要是合同统计但是结果集是要从转换成商机中的结果中取
        //
        //统计线索数量
        Integer allClueNum = reportMpper.getNumberClueByDuration(beginCreateTime, endCreateTime);
        //有效线索数量  已分配1  进行中2  回收3  伪线索4   转换成商机6
        //有效线索的状态 为  1   2   6
        Integer allClueNumByStatus = reportMpper.getNumberClueByDurationAndStatus(beginCreateTime, endCreateTime);
        //商机数量
        Integer allBussinessNum=reportMpper.getNumberBussinessByDurationAndStatus(beginCreateTime, endCreateTime);
        //合同数量
        Integer allContactNum=reportMpper.getNumberContactByDurationAndStatus(beginCreateTime, endCreateTime);
        //封装返回题
        vulnerabilityMap.setCluesNums(allClueNum);
        vulnerabilityMap.setEffectiveCluesNums(allClueNumByStatus);
        vulnerabilityMap.setBusinessNums(allBussinessNum);
        vulnerabilityMap.setContractNums(allContactNum);
        return vulnerabilityMap;
    }

    @Override
    public List<BusinessStatic> getBusinessChangeStatistics(String beginCreateTime, String endCreateTime) {
        //计算固定时间段内的商机总数

        //计算不同员工的


        return null;
    }

}